/*
 * Polyvaccine a Polymorphic exploit detection engine.
 *
 * Copyright (C) 2009  Luis Campo Giralte
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 * Written by Luis Campo Giralte <luis.camp0.2009@gmail.com> 2009
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include "examples.h"
#include "examples64.h"
#include "examples64freebsd.h"
#include <getopt.h>
#include "../utils/interfaces.h"

#define MAX_EXECUTION_BUFFER 2048

static struct option long_options[] = {
        {"case",                required_argument,      0, 'c'},
        {"offset",              required_argument,      0, 'o'},
        {"verbose",            	no_argument,            0, 'v'},
        {0, 0, 0, 0}
};

static char *short_options = "c:o:v";

void usage(char *prog) {
        fprintf(stdout,"Usage %s [options(s)]\n",prog);
	fprintf(stdout,"The options are:\n");
	fprintf(stdout,"\t-c, --case <number>			Select a specific payload for testing.\n");	
        fprintf(stdout,"\t\t\t1 - x86 64 bits\t - exit 1 syscall\n");
        fprintf(stdout,"\t\t\t2 - x86 64 bits\t - exit 9 syscall\n");
        fprintf(stdout,"\t\t\t3 - x86 32 bits\t - exit 0 syscall\n");
        fprintf(stdout,"\t\t\t4 - x86 32 bits\t - loop for with write syscall\n");
        fprintf(stdout,"\t\t\t5 - x86 32 bits\t - admmutate engine with write syscall\n");
        fprintf(stdout,"\t\t\t6 - x86 32 bits\t - encoder fnstenv engine with shellcode\n");
        fprintf(stdout,"\t\t\t7 - x86 32 bits\t - eggdrop exploit\n");
        fprintf(stdout,"\t\t\t8 - x86 32 bits\t - apache exploit\n");
        fprintf(stdout,"\t\t\t9 - x86 64 bits\t - shellcode\n");
        fprintf(stdout,"\t\t\t10- x86 32 bits\t - alpha mixed engine with backdoor.\n");
        fprintf(stdout,"\t\t\t11- x86 64 bits\t - add root user to the system.\n");
        fprintf(stdout,"\t\t\t12- x86 64 bits\t - setuid(0) & chmod (\"/etc/passwd\", 0777) & exit(0).\n");
        fprintf(stdout,"\t\t\t13- x86 64 bits\t - Disable ASLR Security.\n");
        fprintf(stdout,"\t\t\t14- x86 64 bits\t - exit 1 syscall with 7 nop bytes.\n");
        fprintf(stdout,"\t\t\t15- HTTP header\t - HTTP request for test false positives.\n");
	fprintf(stdout,"\t-o, --offset <value>			Sets the start offset of the payload.\n");
	fprintf(stdout,"\t-v, --verbose\n");
        fprintf(stdout,"\n");
        return;
}


void sendbuffer(unsigned char *buffer,int size,int offset){
	DBusError err;
   	DBusConnection* conn;
	DBusMessageIter iter,dataIter;
	DBusMessageIter s_iter,e_iter;
   	int ret,i;
	dbus_int32_t start_offset[8]; 
	dbus_int32_t *s_off,*e_off; 
	dbus_int32_t end_offset[8];  
 
	dbus_error_init(&err);
   	conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
   	if (dbus_error_is_set(&err)) { 
      		fprintf(stderr, "Connection Error (%s)\n", err.message); 
      		dbus_error_free(&err); 
   	}
	if(conn == NULL) {
		exit(-1);
	}
   	ret = dbus_bus_request_name(conn, "test.method.server", 
        	DBUS_NAME_FLAG_REPLACE_EXISTING 
         	,&err);
   	if (dbus_error_is_set(&err)) { 
      		fprintf(stderr, "Name Error (%s)\n", err.message); 
      		dbus_error_free(&err); 
   	}
	if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { 
      		exit(1);
   	}

   	DBusMessage* msg;
   	DBusMessageIter args;
 
	msg = dbus_message_new_signal(POLYVACCINE_DETECTION_OBJECT, // object name of the signal
        	POLYVACCINE_DETECTION_INTERFACE, // interface name of the signal
         	"Analyze"); // name of the signal
	if (NULL == msg){ 
      		fprintf(stderr, "Message Null\n"); 
      		exit(1); 
	}

	dbus_uint32_t hash = 5000;
	dbus_uint32_t seq = 128;
	unsigned char *newbuffer = malloc(MAX_EXECUTION_BUFFER);
	memset(newbuffer,0,MAX_EXECUTION_BUFFER);
	memcpy(newbuffer,buffer,size);

	/* Sends a full segment to the detector
	 * 
	 * 1 - arrray with the buffer and its lenght.
	 * 2 - the hash of the connection flow.
	 * 3 - the sequence number.
	 */
	dbus_message_iter_init_append(msg,&iter);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &dataIter);
        dbus_message_iter_append_fixed_array(&dataIter, DBUS_TYPE_BYTE, &newbuffer, size);
        dbus_message_iter_close_container(&iter, &dataIter);

	dbus_message_iter_append_basic(&iter,DBUS_TYPE_UINT32,&hash);
	dbus_message_iter_append_basic(&iter,DBUS_TYPE_UINT32,&seq);

	for (i=0;i<8;i++){start_offset[i] = 0;end_offset[i]=0; }
	start_offset[0] = 0;
	end_offset[0] = offset;
	s_off = start_offset;
	e_off = end_offset;

	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,"ii", &s_iter);
        dbus_message_iter_append_fixed_array(&s_iter, DBUS_TYPE_INT32, &s_off, 8);
        dbus_message_iter_close_container(&iter, &s_iter);

	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ii", &e_iter);
        dbus_message_iter_append_fixed_array(&e_iter, DBUS_TYPE_INT32, &e_off, 8);
        dbus_message_iter_close_container(&iter, &e_iter);

	if (!dbus_connection_send(conn, msg, NULL)) { 
      		fprintf(stderr, "Out Of Memory!\n"); 
      		exit(1);
   	}
   	dbus_connection_flush(conn);
   	dbus_message_unref(msg);
}


void main(int argc, char **argv) {
	int c,option_index,len;
	int case_n;
	int start_offset = 0;
	int verbose = 0;
	unsigned char *buffer = NULL;

        while((c = getopt_long(argc,argv,short_options,
                            long_options, &option_index)) != -1) {
                switch (c) {
                        case 'c':
                               	case_n = atoi(optarg);
                                break;
                        case 'o':
                              	start_offset = atoi(optarg); 
                                break;
                        case 'v':
                               	verbose ++; 
                                break;
                        case 'h':
                                usage(argv[0]);
                                exit(0);
                        default:
                                abort ();
                }
        }


	if(case_n == 0){
		usage(argv[0]);
		exit(-1);
	}

	switch(case_n) {
		case 1:
             		buffer = exit_1_64bits;
			len = size_exit_1_64bits;	
             		break;
		case 2:
             		buffer = exit_9_64bits;
			len = size_exit_9_64bits;
			break;
		case 3:
			buffer = exit_0_32bits;
			len = size_exit_0_32bits;
			break;
		case 4:
			buffer = bucle_1_32bits;
			len = size_bucle_1_32bits;
			break;
		case 5:
			len = size_admmutate_1_32bits;
			buffer = admmutate_1_32bits;
			break;
		case 6:
			len = size_fnstenv_1_32bits;
			buffer = fnstenv_1_32bits;
			break;
		case 7:
			len = size_eggdrop_32bits;
			buffer = eggdrop_32bits;
			break;
		case 8:
			buffer = apache_32bits;
			len = size_apache_32bits;
			break;
		case 9:
			buffer = shellcode_64bits;
			len = size_shellcode_64bits;
			break;
		case 10:
			buffer = alpha_mixed_32bits;
			len = sizeof(alpha_mixed_32bits);
			break;
		case 11:
			buffer = add_root_user_64bits; 
			len = strlen(add_root_user_64bits);
			break;
		case 12:
			buffer = setuid_64bits; 
			len = size_setuid_64bits;
			break;
		case 13:
			buffer = disable_aslr_64bits; 
			len = strlen(disable_aslr_64bits);
			break;
		case 14:
			buffer = exit_1_nops_64bits;
			len = size_exit_1_nops_64bits;
			break;
		case 15:
			buffer = http_request_header;
			len = strlen(http_request_header);
			break;
           	default:
             		abort ();
	}
	if(buffer == NULL) {
		usage(argv[0]);
		exit(0);
	}
	if(verbose>0)
		printf("Sending buffer of %d bytes from offset %d \n",len,start_offset);
	sendbuffer(buffer,len,start_offset);
	exit(0);
}
